﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Effects.Filters;
using Effects.Effects;
using Effects.Effects.Tools;
using Effects.Effects.GuiParts;


namespace EffectsPack
{
    /// <summary>
    ///  Graphic equalizer
    /// </summary>
    public class GraphicEqualizer : Effect
    {
        #region controls
        // user controlled parameters, one for every octave band

        #region footswitch

        /// <summary>
        ///  Footswitch for by passing effect.
        /// </summary>
        private Footswitch footswitch;

        /// <summary>
        ///  Led indicating On/Off state.
        /// </summary>
        private LED led;

        /// <summary>
        ///  Synchornizer for footswitch and led.
        /// </summary>
        private FootswitchLedSynchronizer synchronizer;


        /// <summary>
        ///  Key for footswitch settings.
        /// </summary>
        private int footswitchKey = 0;

        #endregion

        #region freq_32_hz

        /// <summary>
        ///  Slider controlling gain at 32 Hz.
        /// </summary>
        private Slider freq_32_Slider;

        /// <summary>
        ///  Gain of the 32 Hz peak filter.
        /// </summary>
        private double freq_32_gain;

        /// <summary>
        ///  Controls width of the peak at 32 Hz.
        /// </summary>
        private double freq_32_Q;

        /// <summary>
        ///  Peak filter centered at 32 Hz
        /// </summary>
        private SecondOrderFilter freq_32_filter;

        /// <summary>
        ///  Center frequancy at 32Hz peak.
        /// </summary>
        private const double freq_32_frequency = 31.5;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_32_frequencyLow = 22;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_32_frequencyUp = 45;

        /// <summary>
        ///  Key for the 32 Hz parameter.
        /// </summary>
        private const int freq_32_key = 1;

        #endregion

        #region freq_63_hz

        /// <summary>
        ///  Slider controlling gain at 63 Hz.
        /// </summary>
        private Slider freq_63_Slider;

        /// <summary>
        ///  Gain of the peak filter at 63 Hz.
        /// </summary>
        private double freq_63_gain;

        /// <summary>
        ///  Controls width of the peak at 63 Hz.
        /// </summary>
        private double freq_63_Q;

        /// <summary>
        ///  Peak filter centered at 63 Hz.
        /// </summary>
        private SecondOrderFilter freq_63_filter;

        /// <summary>
        ///  Center frequancy of 63 Hz peak.
        /// </summary>
        private const double freq_63_frequency = 63;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_63_frequencyLow = 45;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_63_frequencyUp = 89;

        /// <summary>
        ///  Key for the 63 Hz parameter.
        /// </summary>
        private const int freq_63_Key = 2;

        #endregion

        #region freq_125_hz

        /// <summary>
        ///  Slider controlling gain at 125 Hz.
        /// </summary>
        private Slider freq_125_Slider;

        /// <summary>
        ///  Gain of the peak filter at 125 Hz.
        /// </summary>
        private double freq_125_gain;

        /// <summary>
        ///  Controls width of the peak at 125 Hz.
        /// </summary>
        private double freq_125_Q;

        /// <summary>
        ///  Peak filter centered at 125 Hz
        /// </summary>
        private SecondOrderFilter freq_125_filter;

        /// <summary>
        ///  125 Hz
        /// </summary>
        private const double freq_125_frequency = 125;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_125_frequencyLow = 89;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_125_frequencyUp = 176;

        /// <summary>
        ///  Key for the 125 Hz parameter
        /// </summary>
        private const int freq_125_Key = 3;

        #endregion

        #region freq_250_hz

        /// <summary>
        ///  Slider controlling gain at 250 Hz.
        /// </summary>
        private Slider freq_250_Slider;

        /// <summary>
        ///  Gain of the peak filter at 250 Hz.
        /// </summary>
        private double freq_250_gain;

        /// <summary>
        ///  Controls width of the peak at 250 Hz.
        /// </summary>
        private double freq_250_Q;

        /// <summary>
        ///  Peak filter centered at 250 Hz
        /// </summary>
        private SecondOrderFilter freq_250_filter;

        /// <summary>
        ///  250 Hz.
        /// </summary>
        private const double freq_250_frequency = 250;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_250_frequencyLow = 176;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_250_frequencyUp = 353;

        /// <summary>
        ///  Key for the 250 Hz parameter
        /// </summary>
        private const int freq_250_Key = 4;

        #endregion

        #region freq_500_hz

        /// <summary>
        ///  Slider controlling gain at 500 Hz.
        /// </summary>
        private Slider freq_500_Slider;

        /// <summary>
        ///  Gain of the peak filter at 500 Hz.
        /// </summary>
        private double freq_500_gain;

        /// <summary>
        ///  Controls width of the peak at 500 Hz.
        /// </summary>
        private double freq_500_Q;

        /// <summary>
        ///  Peak filter centered at 500 Hz.
        /// </summary>
        private SecondOrderFilter freq_500_filter;

        /// <summary>
        ///  500 Hz.
        /// </summary>
        private const double freq_500_frequncy = 500;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_500_frequencyLow = 353;
        
        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_500_frequencyUp = 707;

        /// <summary>
        ///  Key for the 500 Hz parameter.
        /// </summary>
        private const int freq_500_Key = 5;

        #endregion

        #region freq_1000_hz

        /// <summary>
        ///  Slider controlling gain at 1000 Hz.
        /// </summary>
        private Slider freq_1000_Slider;

        /// <summary>
        ///  Gain of the peak filter at 1000 Hz.
        /// </summary>
        private double freq_1000_gain;

        /// <summary>
        ///  Controls width of the peak at 1000 Hz.
        /// </summary>
        private double freq_1000_Q;

        /// <summary>
        ///  Peak filter centered at 1000 Hz
        /// </summary>
        private SecondOrderFilter freq_1000_filter;

        /// <summary>
        ///  1000 Hz
        /// </summary>
        private const double freq_1000_frequency = 1000;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_1000_frequencyLow = 707;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_1000_frequencyUp = 1414;

        /// <summary>
        ///  Key for the 1000 Hz parameter.
        /// </summary>
        private const int freq_1000_Key = 6;

        #endregion

        #region freq_2000_hz

        /// <summary>
        ///  Slider controlling gain at 2000 Hz.
        /// </summary>
        private Slider freq_2000_Slider;

        /// <summary>
        ///  Gain of the peak filter at 2000 Hz.
        /// </summary>
        private double freq_2000_gain;

        /// <summary>
        ///  Controls width of the peak at 2000 Hz.
        /// </summary>
        private double freq_2000_Q;

        /// <summary>
        ///  Peak filter centered at 2000 Hz.
        /// </summary>
        private SecondOrderFilter freq_2000_filter;

        /// <summary>
        ///  2000 Hz
        /// </summary>
        private const double freq_2000_frequency = 2000;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_2000_frequencyLow = 1414;
        
        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_2000_frequencyUp = 2828;

        /// <summary>
        ///  Key for the 2000 Hz parameter.
        /// </summary>
        private const int freq_2000_Key = 7;

        #endregion

        #region freq_4000_hz

        /// <summary>
        ///  Slider controlling gain at 4000 Hz.
        /// </summary>
        private Slider freq_4000_Slider;

        /// <summary>
        ///  Gain of the peak filter at 4000 Hz.
        /// </summary>
        private double freq_4000_gain;

        /// <summary>
        ///  Controls width of the peak at 4000 Hz.
        /// </summary>
        private double freq_4000_Q;

        /// <summary>
        ///  Peak filter centered at 4000 Hz.
        /// </summary>
        private SecondOrderFilter freq_4000_filter;

        /// <summary>
        ///  4000 Hz
        /// </summary>
        private const double freq_4000_frequency = 4000;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_4000_frequencyLow = 2828;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_4000_frequencyUp = 5656;

        /// <summary>
        ///  Key for the 4000 Hz parameter.
        /// </summary>
        private const int freq_4000_Key = 8;

        #endregion

        #region freq_8000_hz

        /// <summary>
        ///  Slider controlling gain at 8000 Hz.
        /// </summary>
        private Slider freq_8000_Slider;

        /// <summary>
        ///  Gain of the peak filter at 8000 Hz.
        /// </summary>
        private double freq_8000_gain;

        /// <summary>
        ///  Controls width of the peak at 8000 Hz.
        /// </summary>
        private double freq_8000_Q;

        /// <summary>
        ///  Peak filter centered at 8000 Hz.
        /// </summary>
        private SecondOrderFilter freq_8000_filter;

        /// <summary>
        ///  8000 Hz
        /// </summary>
        private const double freq_8000_frequency = 8000;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_8000_frequencyLow = 5656;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_8000_frequencyUp = 11313;

        /// <summary>
        ///  Key for the 8000 Hz parameter.
        /// </summary>
        private const int freq_8000_Key = 9;

        #endregion

        #region freq_16000_hz

        /// <summary>
        ///  Slider controlling gain at 16000 Hz.
        /// </summary>
        private Slider freq_16000_Slider;

        /// <summary>
        ///  Gain of the peak filter at 16000 Hz.
        /// </summary>
        private double freq_16000_gain;

        /// <summary>
        ///  Controls width of the peak at 16000 Hz.
        /// </summary>
        private double freq_16000_Q;

        /// <summary>
        ///  Peak filter centered at 16000 Hz.
        /// </summary>
        private SecondOrderFilter freq_16000_filter;

        /// <summary>
        ///  16000 Hz
        /// </summary>
        private const double freq_16000_frequency = 16000;

        /// <summary>
        ///  Lower border frequency at 32Hz peak
        /// </summary>
        private const double freq_16000_frequencyLow = 11313;

        /// <summary>
        ///  Upper border frequency at 32Hz peak
        /// </summary>
        private const double freq_16000_frequencyUp = 22627;

        /// <summary>
        ///  Key for the 16000 Hz parameter.
        /// </summary>
        private const int freq_16000_Key = 10;

        #endregion

        #region master
        // master volume level

        /// <summary>
        ///  Current master volume level.
        /// </summary>
        private double master;

        /// <summary>
        ///  Controls master volume level.
        /// </summary>
        private Slider MasterSlider;

        /// <summary>
        ///  Key for master volume parameter.
        /// </summary>
        private const int masterKey = 11;

        #endregion

        #endregion

        #region constructor
        // constructor and initialization

        /// <summary>
        ///  Creates new instance of EQ
        /// </summary>
        public GraphicEqualizer()
        {
            BackgroundImage =  System.Drawing.Image.FromStream(new System.IO.MemoryStream(EffectsPack.Properties.Resources.GraphicEq));
            Size = BackgroundImage.Size;
            InitializeFilters();
            InitializeQs();

            SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint | System.Windows.Forms.ControlStyles.UserPaint | System.Windows.Forms.ControlStyles.DoubleBuffer, true);
            InitializeComponents();
            InitializeFootswitch();
        }

        /// <summary>
        ///  Initializes bandwidths for filters
        /// </summary>
        private void InitializeQs()
        {
            //subBassQ = 1F / Math.Sqrt(2);
            freq_32_Q = Math.Pow(2, 2 / 3);
            freq_63_Q = freq_32_Q;
            freq_125_Q = freq_32_Q;
            freq_250_Q = freq_32_Q;
            freq_500_Q = freq_32_Q;
            freq_1000_Q = freq_32_Q;
            freq_2000_Q = freq_32_Q;
            freq_4000_Q = freq_32_Q;
            freq_8000_Q = freq_32_Q;
            freq_16000_Q = freq_32_Q;
        }

        /// <summary>
        ///  Initializes filters
        /// </summary>
        private void InitializeFilters()
        {
            freq_32_filter = SecondOrderFilter.CreateBandPass(freq_32_frequencyLow, freq_32_frequencyUp, (int)sampleRate);
            freq_63_filter = SecondOrderFilter.CreateBandPass(freq_63_frequencyLow, freq_63_frequencyUp, (int)sampleRate);
            freq_125_filter = SecondOrderFilter.CreateBandPass(freq_125_frequencyLow, freq_125_frequencyUp, (int)sampleRate);
            freq_250_filter = SecondOrderFilter.CreateBandPass(freq_250_frequencyLow, freq_250_frequencyUp, (int)sampleRate);
            freq_500_filter = SecondOrderFilter.CreateBandPass(freq_500_frequencyLow, freq_500_frequencyUp, (int)sampleRate);
            freq_1000_filter = SecondOrderFilter.CreateBandPass(freq_1000_frequencyLow, freq_1000_frequencyUp, (int)sampleRate);
            freq_2000_filter = SecondOrderFilter.CreateBandPass(freq_2000_frequencyLow, freq_2000_frequencyUp, (int)sampleRate);
            freq_4000_filter = SecondOrderFilter.CreateBandPass(freq_4000_frequencyLow, freq_4000_frequencyUp, (int)sampleRate);
            freq_8000_filter = SecondOrderFilter.CreateBandPass(freq_8000_frequencyLow, freq_8000_frequencyUp, (int)sampleRate);
            freq_16000_filter = SecondOrderFilter.CreateBandPass(freq_16000_frequencyLow, freq_16000_frequencyUp, (int)sampleRate);

        }

        /// <summary>
        ///  Initializes potentiometers
        /// </summary>
        private void InitializeComponents()
        {
            freq_32_Slider = new Slider();
            freq_32_Slider.MinValue = 0;
            freq_32_Slider.MaxValue = 1;
            freq_32_Slider.Size = new System.Drawing.Size(20, 150);
            freq_32_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_32_Slider.Location = new System.Drawing.Point(8, 30);
            freq_32_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq32SliderMoved);
            freq_32_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_32_Slider);
            freq_32_Slider.Reset();

            freq_63_Slider = new Slider();
            freq_63_Slider.MinValue = 0;
            freq_63_Slider.MaxValue = 1;
            freq_63_Slider.Size = new System.Drawing.Size(20, 150);
            freq_63_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_63_Slider.Location = new System.Drawing.Point(35, 30);
            freq_63_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq63SliderMoved);
            freq_63_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_63_Slider);
            freq_63_Slider.Reset();

            freq_125_Slider = new Slider();
            freq_125_Slider.MinValue = 0;
            freq_125_Slider.MaxValue = 1;
            freq_125_Slider.Size = new System.Drawing.Size(20, 150);
            freq_125_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_125_Slider.Location = new System.Drawing.Point(65, 30);
            freq_125_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq125SliderMoved);
            freq_125_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_125_Slider);
            freq_125_Slider.Reset();

            freq_250_Slider = new Slider();
            freq_250_Slider.MinValue = 0;
            freq_250_Slider.MaxValue = 1;
            freq_250_Slider.Size = new System.Drawing.Size(20, 150);
            freq_250_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_250_Slider.Location = new System.Drawing.Point(92, 30);
            freq_250_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq250SliderMoved);
            freq_250_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_250_Slider);
            freq_250_Slider.Reset();

            freq_500_Slider = new Slider();
            freq_500_Slider.MinValue = 0;
            freq_500_Slider.MaxValue = 1;
            freq_500_Slider.Size = new System.Drawing.Size(20, 150);
            freq_500_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_500_Slider.Location = new System.Drawing.Point(120, 30);
            freq_500_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq500SliderMoved);
            freq_500_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_500_Slider);
            freq_500_Slider.Reset();

            freq_1000_Slider = new Slider();
            freq_1000_Slider.MinValue = 0;
            freq_1000_Slider.MaxValue = 1;
            freq_1000_Slider.Size = new System.Drawing.Size(20, 150);
            freq_1000_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_1000_Slider.Location = new System.Drawing.Point(150, 30);
            freq_1000_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq1000SliderMoved);
            freq_1000_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_1000_Slider);
            freq_1000_Slider.Reset();

            freq_2000_Slider = new Slider();
            freq_2000_Slider.MinValue = 0;
            freq_2000_Slider.MaxValue = 1;
            freq_2000_Slider.Size = new System.Drawing.Size(20, 150);
            freq_2000_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_2000_Slider.Location = new System.Drawing.Point(180, 30);
            freq_2000_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq2000SliderMoved);
            freq_2000_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_2000_Slider);
            freq_2000_Slider.Reset();

            freq_4000_Slider = new Slider();
            freq_4000_Slider.MinValue = 0;
            freq_4000_Slider.MaxValue = 1;
            freq_4000_Slider.Size = new System.Drawing.Size(20, 150);
            freq_4000_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_4000_Slider.Location = new System.Drawing.Point(210, 30);
            freq_4000_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq4000SliderMoved);
            freq_4000_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_4000_Slider);
            freq_4000_Slider.Reset();

            freq_8000_Slider = new Slider();
            freq_8000_Slider.MinValue = 0;
            freq_8000_Slider.MaxValue = 1;
            freq_8000_Slider.Size = new System.Drawing.Size(20, 150);
            freq_8000_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_8000_Slider.Location = new System.Drawing.Point(240, 30);
            freq_8000_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq8000SliderMoved);
            freq_8000_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_8000_Slider);
            freq_8000_Slider.Reset();

            freq_16000_Slider = new Slider();
            freq_16000_Slider.MinValue = 0;
            freq_16000_Slider.MaxValue = 1;
            freq_16000_Slider.Size = new System.Drawing.Size(20, 150);
            freq_16000_Slider.BackColor = System.Drawing.Color.Transparent;
            freq_16000_Slider.Location = new System.Drawing.Point(270, 30);
            freq_16000_Slider.SliderPositionChanged += new SliderPositionChanged(this.Freq16000SliderMoved);
            freq_16000_Slider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(freq_16000_Slider);
            freq_16000_Slider.Reset();

            MasterSlider = new Slider();
            MasterSlider.MinValue = 0;
            MasterSlider.MaxValue = 1;
            MasterSlider.Size = new System.Drawing.Size(20, 150);
            MasterSlider.BackColor = System.Drawing.Color.Transparent;
            MasterSlider.Location = new System.Drawing.Point(330, 30);
            MasterSlider.SliderPositionChanged += new SliderPositionChanged(this.MasterMoved);
            MasterSlider.Orientation = SliderOrientation.Vertical;
            this.Controls.Add(MasterSlider);
            MasterSlider.Reset();

        }

        /// <summary>
        ///  Iniializes footswitch and led.
        /// </summary>
        private void InitializeFootswitch()
        {
            // footswitch
            footswitch = new Footswitch();
            switchedOn = true;
            footswitch.On = true;
            footswitch.Switched += new FootswitchSwitchedEventHandler(this.FootswitchSwitched);
            footswitch.Location = new System.Drawing.Point(360, 110);
            Controls.Add(footswitch);

            // led
            led = new LED();
            led.On = true;
            led.Location = new System.Drawing.Point(365, 40);
            Controls.Add(led);

            // synchronization
            synchronizer = new FootswitchLedSynchronizer(footswitch, led);
        }

        #endregion

        #region effects_properties

        /// <summary>
        ///  Time interval between adjacent samples in seconds
        /// </summary>
        private double step;

        /// <summary>
        ///  Gets or sets the sampling rate
        /// </summary>
        public override uint SampleRate
        {
            get { return base.SampleRate; }
            set
            {
                sampleRate = value;
                step = 1F / sampleRate;

                InitializeFilters();
                signalPower = new RMS(0.25, (int)sampleRate);
                delay = new ConstantDelayLine(0.25, (int)sampleRate);
                SetUsedCoefs();
                     
            }
        }

        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_32_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_63_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_125_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_250_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_500_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_1000_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_2000_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_4000_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_8000_used;
        /// <summary>
        ///  Indicates whether corsponding filter is used
        /// </summary>
        private bool freq_16000_used;

        /// <summary>
        ///  Determines which filter are used at the moment.
        /// </summary>
        private void SetUsedCoefs()
        {
            double maxFreq = sampleRate / 2;

            freq_32_used = freq_32_frequencyUp < maxFreq;
            freq_63_used = freq_63_frequencyUp < maxFreq;
            freq_125_used = freq_125_frequencyUp < maxFreq;
            freq_250_used = freq_250_frequencyUp < maxFreq;
            freq_500_used = freq_500_frequencyUp < maxFreq;
            freq_1000_used = freq_1000_frequencyUp < maxFreq;
            freq_2000_used = freq_2000_frequencyUp < maxFreq;
            freq_4000_used = freq_4000_frequencyUp < maxFreq;
            freq_8000_used = freq_8000_frequencyUp < maxFreq;
            freq_16000_used = freq_16000_frequencyUp < maxFreq;
        }
        
        /// <summary>
        ///  Gets the name of the effect.
        /// </summary>
        public override string Name
        {
            get { return "Graphic EQ v2.0"; }
        }

        #endregion

        #region main_work
        // main method

        /// <summary>
        ///  Measures the signal to prevne from overloading.
        /// </summary>
        private RMS signalPower;

        /// <summary>
        ///  Compensates rms measurement method.
        /// </summary>
        private ConstantDelayLine delay;

        /// <summary>
        ///  Effects the input signal.
        /// </summary>
        /// <param name="data"> Input signal </param>
        /// <returns> Effected output signal </returns>
        public override double[] effect(double[] data)
        {
            if (switchedOn)
            {
                double[] outData = new double[data.Length];
                for (int i = 0; i < data.Length; i++)
                {
                    outData[i] = 0;
                    if (freq_32_used)
                        outData[i] += freq_32_gain * freq_32_filter.Step(data[i]);
                    if (freq_63_used)
                        outData[i] += freq_63_gain * freq_63_filter.Step(data[i]);
                    if (freq_125_used)
                        outData[i] += freq_125_gain * freq_125_filter.Step(data[i]);
                    if (freq_250_used)
                        outData[i] += freq_250_gain * freq_250_filter.Step(data[i]);
                    if (freq_500_used)
                        outData[i] += freq_500_gain * freq_500_filter.Step(data[i]);
                    if (freq_1000_used)
                        outData[i] += freq_1000_gain * freq_1000_filter.Step(data[i]);
                    if (freq_2000_used)
                        outData[i] += freq_2000_gain * freq_2000_filter.Step(data[i]);
                    if (freq_4000_used)
                        outData[i] += freq_4000_gain * freq_4000_filter.Step(data[i]);
                    if (freq_8000_used)
                        outData[i] += freq_8000_gain * freq_8000_filter.Step(data[i]);
                    if (freq_16000_used)
                        outData[i] += freq_16000_gain * freq_16000_filter.Step(data[i]);
                    outData[i] *= master;
                }
                return outData;
            }

            return data;
        }

        #endregion

        #region controls_event_handlers
        // handling events from controls

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_32_Slider"/> event handler. Controls the gain at 32 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq32SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_32_gain = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_32_key, freq_32_gain);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_63_Slider"/> event handler. Controls the gain at 63 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq63SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_63_gain = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_63_Key, freq_63_gain);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_125_Slider"/> event handler. Controls the gain at 125 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq125SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
             this.freq_125_gain = e.Value;
 
            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_125_Key, freq_125_gain);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_250_Slider"/> event handler. Controls the gain at 250 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq250SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_250_gain = e.Value;
   
            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_250_Key, freq_250_gain);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_500_Slider"/> event handler. Controls the gain at 500 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq500SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_500_gain = e.Value;
 
            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_500_Key, freq_500_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);

        }
        
        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_1000_Slider"/> event handler. Controls the gain at 1000 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq1000SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_1000_gain = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_1000_Key, freq_1000_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_2000_Slider"/> event handler. Controls the gain at 2000 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq2000SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_2000_gain = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_2000_Key, freq_2000_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_4000_Slider"/> event handler. Controls the gain at 4000 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq4000SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_4000_gain = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_4000_Key, freq_4000_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_8000_Slider"/> event handler. Controls the gain at 8000 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq8000SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
           this.freq_8000_gain = e.Value;
  
            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_8000_Key, freq_8000_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  <see cref="GraphicEqualizer.freq_16000_Slider"/> event handler. Controls the gain at 16000 Hz.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void Freq16000SliderMoved(object sender, SliderPositionChangedEventArgs e)
        {
            this.freq_16000_gain = e.Value;
  
            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(freq_16000_Key, freq_16000_gain);
            if (this.SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  Master slider event handler. Sets master volume level.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="e"> Event arguments </param>
        private void MasterMoved(object sender, SliderPositionChangedEventArgs e)
        {
            master = e.Value;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(masterKey, master);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        /// <summary>
        ///  Footswitch.Switched event handler. According to the event arguments signal bypasses or runs through the effect.
        /// </summary>
        /// <param name="sender"> Object that has raised the event. </param>
        /// <param name="args"> Event Arguments </param>
        private void FootswitchSwitched(object sender, FootswitchSwitchedEventArgs args)
        {
            this.switchedOn = args.On;

            // raise the event
            if (this.SettingsChanged != null)
            {
                EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(footswitchKey, switchedOn);
                this.SettingsChanged(this, changeArgs);
            }
        }

        #endregion

        #region settings
        // getting and setting the settings of EQ

        /// <summary>
        ///  Raised when any parameter is changed
        /// </summary>
        public override event EffectSettingsChangedDelegate SettingsChanged;

        /// <summary>
        ///  Gets all current settings of the effect.
        /// </summary>
        /// <returns> All current seetings </returns>
        public override object[] GetAllSettings()
        {
            object[] settings = new object[12];

            settings[0] = switchedOn;
            settings[1] = freq_32_gain;
            settings[2] = freq_63_gain;
            settings[3] = freq_125_gain;
            settings[4] = freq_250_gain;
            settings[5] = freq_500_gain;
            settings[6] = freq_1000_gain;
            settings[7] = freq_2000_gain;
            settings[8] = freq_4000_gain;
            settings[9] = freq_8000_gain;
            settings[10] = freq_16000_gain;
            settings[11] = master;

            return settings;
        }

        /// <summary>
        ///  Sets all settings.
        /// </summary>
        /// <param name="settings"> All settings of the effect. This argument should be output of GetAllSettings method that has been called previously. </param>
        public override void SetAllSettings(object[] settings)
        {
            switchedOn = (bool)settings[0];
            synchronizer.SetValue(switchedOn);

            freq_32_gain = (double)settings[1];
            freq_32_Slider.SetValue(freq_32_gain);

            freq_63_gain = (double)settings[2];
            freq_63_Slider.SetValue(freq_63_gain);

            freq_125_gain = (double)settings[3];
            freq_125_Slider.SetValue(freq_125_gain);

            freq_250_gain = (double)settings[4];
            freq_250_Slider.SetValue(freq_250_gain);

            freq_500_gain = (double)settings[5];
            freq_500_Slider.SetValue(freq_500_gain);

            freq_1000_gain = (double)settings[6];
            freq_1000_Slider.SetValue(freq_1000_gain);

            freq_2000_gain = (double)settings[7];
            freq_2000_Slider.SetValue(freq_2000_gain);

            freq_4000_gain = (double)settings[8];
            freq_4000_Slider.SetValue(freq_4000_gain);

            freq_8000_gain = (double)settings[9];
            freq_8000_Slider.SetValue(freq_8000_gain);

            freq_16000_gain = (double)settings[10];
            freq_16000_Slider.SetValue(freq_16000_gain);

            master = (double)settings[11];
            MasterSlider.SetValue(master);
        }

        /// <summary>
        ///  Sets one settings
        /// </summary>
        /// <param name="e"> Setting change to be done </param>
        public override void SetSetting(EffectSettingsChangedEventArgs e)
        {
            int key = (int)e.Key;

            if (key == footswitchKey)
            {
                switchedOn = (bool)e.Value;
                synchronizer.SetValue(switchedOn);
                return;
            }

            if (key == freq_32_key)
            {
                freq_32_gain = (double)e.Value;
                freq_32_Slider.SetValue(freq_32_gain);
                return;
            }

            if (key == freq_63_Key)
            {
                freq_63_gain = (double)e.Value;
                freq_63_Slider.SetValue(freq_63_gain);
                return;
            }

            if (key == freq_125_Key)
            {
                freq_125_gain = (double)e.Value;
                freq_125_Slider.SetValue(freq_125_gain);
                return;
            }

            if (key == freq_250_Key)
            {
                freq_250_gain = (double)e.Value;
                freq_250_Slider.SetValue(freq_250_gain);
                return;
            }

            if (key == freq_500_Key)
            {
                freq_500_gain = (double)e.Value;
                freq_500_Slider.SetValue(freq_500_gain);
                return;
            }

            if (key == freq_1000_Key)
            {
                freq_1000_gain = (double)e.Value;
                freq_1000_Slider.SetValue(freq_1000_gain);
                return;
            }

            if (key == freq_2000_Key)
            {
                freq_2000_gain = (double)e.Value;
                freq_2000_Slider.SetValue(freq_2000_gain);
                return;
            }

            if (key == freq_4000_Key)
            {
                freq_4000_gain = (double)e.Value;
                freq_4000_Slider.SetValue(freq_4000_gain);
                return;
            }

            if (key == freq_8000_Key)
            {
                freq_8000_gain = (double)e.Value;
                freq_8000_Slider.SetValue(freq_8000_gain);
                return;
            }

            if (key == freq_16000_Key)
            {
                freq_16000_gain = (double)e.Value;
                freq_16000_Slider.SetValue(freq_16000_gain);
                return;
            }
            if (key == masterKey)
            {
                master = (double)e.Value;
                MasterSlider.SetValue(master);
                return;
            }
        }

        /// <summary>
        ///  Gets parameter description.
        /// </summary>
        /// <returns> EffectParam array descrobing effect's parameters. </returns>
        public override EffectParam[] GetParameters()
        {
            EffectParam[] parameters = new EffectParam[12];

            ListItem[] footswitchState = new ListItem[2];
            footswitchState[0] = new ListItem("Turn on", true);
            footswitchState[1] = new ListItem("Turn off", false);
            parameters[0] = new EffectParam(footswitchKey, "ON/OFF", footswitchState);

            parameters[1] = new EffectParam(freq_32_key, "32 Hz", 0F, 1F);
            parameters[2] = new EffectParam(freq_63_Key, "63 Hz", 0F, 1F);
            parameters[3] = new EffectParam(freq_125_Key, "125 Hz", 0F, 1F);
            parameters[4] = new EffectParam(freq_250_Key, "250 Hz", 0F, 1F);
            parameters[5] = new EffectParam(freq_500_Key, "500 Hz", 0F, 1F);
            parameters[6] = new EffectParam(freq_1000_Key, "1000 Hz", 0F, 1F);
            parameters[7] = new EffectParam(freq_2000_Key, "2000 Hz", 0F, 1F);
            parameters[8] = new EffectParam(freq_4000_Key, "4000 Hz", 0F, 1F);
            parameters[9] = new EffectParam(freq_8000_Key, "8000 Hz", 0F, 1F);
            parameters[10] = new EffectParam(freq_16000_Key, "16000 Hz", 0F, 1F);
            parameters[11] = new EffectParam(masterKey, "Volume level", 0F, 1F);

            return parameters;
        }

        #endregion 
    }
}

